{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Keys and Addresses Exercises"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Requirements\n",
    "\n",
    "    $ pip3 install ethereum\n",
    "    \n",
    "    $ pip3 install bitcoin\n",
    "    \n",
    "    $ pip3 install pycryptodomex\n",
    "    \n",
    "    $ pip3 install jupyter\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import libraries\n",
    "\n",
    "\n",
    "# Vitalik Buterin's Python Library for bitcoin\n",
    "# No longer maintained!\n",
    "# https://pypi.python.org/pypi/bitcoin/1.1.42\n",
    "import bitcoin\n",
    "\n",
    "# Vitalik Buterin's Python Library for Ethereum\n",
    "# https://github.com/ethereum/pyethereum\n",
    "import ethereum\n",
    "\n",
    "# Wrong source of SHA3 (FIPS-202 not Keccak-256)\n",
    "from hashlib import sha3_256 as hashlib_sha3\n",
    "\n",
    "# Both FIP-202 SHA-3 and Keccak-256 from pycryptodomex\n",
    "from Crypto.Hash import SHA3_256 as crypto_sha3\n",
    "from Crypto.Hash import keccak as crypto_keccak\n",
    "\n",
    "# Ethereum library implements Keccak, but calls it sha3\n",
    "from ethereum.utils import sha3 as ethereum_sha3\n",
    "\n",
    "from rlp.utils import decode_hex, encode_hex\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "privkey_hex = \"f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "privkey = decode_hex(privkey_hex)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Use pybitcointools (bitcoin) library's elliptic curve functions to calculate the public key\n",
    "\n",
    "pubkey = bitcoin.privtopub(privkey)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "pubkey_hex = encode_hex(pubkey)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Public Key: 046e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0\n"
     ]
    }
   ],
   "source": [
    "print(\"Public Key: \" + pubkey_hex)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x (hex) : 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b\n",
      "y (hex) : 83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0\n",
      "x (int) :  49790390825249384486033144355916864607616083520101638681403973749255924539515\n",
      "y (int) :  59574132161899900045862086493921015780032175291755807399284007721050341297360\n"
     ]
    }
   ],
   "source": [
    "pubkey_without_prefix = pubkey_hex[2:]\n",
    "x_hex = pubkey_without_prefix[:64]\n",
    "y_hex = pubkey_without_prefix[64:]\n",
    "print(\"x (hex) : \" + x_hex)\n",
    "print(\"y (hex) : \" + y_hex)\n",
    "\n",
    "x = int(x_hex, 16)\n",
    "y = int(y_hex, 16)\n",
    "print(\"x (int) : \", x)\n",
    "print(\"y (int) : \", y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Prove pubkey is a point on the curve\n",
    "\n",
    "# p is the prime order of the elliptic curve field\n",
    "p = 115792089237316195423570985008687907853269984665640564039457584007908834671663\n",
    "\n",
    "(x ** 3 + 7 - y**2) % p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\n",
      "Hash Function is Keccak-256\n"
     ]
    }
   ],
   "source": [
    "# Which \"SHA3\" am I using?\n",
    "\n",
    "# Uncomment below to try various options\n",
    "#test_hash = hashlib_sha3(b\"\").hexdigest()\n",
    "#test_hash = crypto_sha3.new(b\"\").hexdigest()\n",
    "#test_hash = crypto_keccak.new(digest_bits=256, data=b\"\").hexdigest()\n",
    "#test_hash = encode_hex(ethereum_sha3(b\"\"))\n",
    "\n",
    "\n",
    "print(test_hash)\n",
    "\n",
    "if test_hash == \"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\":\n",
    "    print(\"Hash Function is Keccak-256\")\n",
    "elif test_hash == \"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a\":\n",
    "    print(\"Hash Function is FIP-202 SHA-3\")\n",
    "else: \n",
    "    print(\"Oops! Can't identify SHA3\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Public Key Hash: 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9\n"
     ]
    }
   ],
   "source": [
    "hex_hash = encode_hex(ethereum_sha3(decode_hex(pubkey_without_prefix)))\n",
    "print (\"Public Key Hash: \" + hex_hash)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Ethereum Address: 0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9\n"
     ]
    }
   ],
   "source": [
    "print(\"Ethereum Address: 0x\" + hex_hash[24:])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
